home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1996 June / EnigmA AMIGA RUN 08 (1996)(G.R. Edizioni)(IT)[!][issue 1996-06][EARSAN CD VII].iso / earcd / c-lang / vbcc.lha / vbcc / regs.c < prev    next >
C/C++ Source or Header  |  1996-05-15  |  37KB  |  869 lines

  1. /*  $VER: vbcc (regs.c) V0.3    */
  2. /*  Registerzuteilung           */
  3.  
  4. #include "opt.h"
  5.  
  6. #ifndef NO_OPTIMIZER
  7.  
  8. int (*savings)[MAXR+1];
  9. int *rvlist;
  10.  
  11. int cmp_savings(const void *v1,const void *v2)
  12. /*  Vergleichsfkt, um rvlist nach savings zu sortieren  */
  13. {
  14.     return savings[*(int *)v2][0]-savings[*(int *)v1][0];
  15. }
  16.  
  17. void insert_regs(struct flowgraph *fg1)
  18. /*  soll mal die blockweise Registervariablenzuteilung einfuegen, im    */
  19. /*  Moment macht es nur Ausgaben                                        */
  20. {
  21.     int i;struct IC *p,*lic=0,*new;struct flowgraph *lfg=0,*fg;
  22.     if(DEBUG&1024) printf("inserting register variables\n");
  23.     fg=fg1;
  24.     while(fg){
  25.         if(DEBUG&2048) printf("block %d:\n",fg->index);
  26.         p=fg->start;
  27.         while(p){
  28.             for(i=1;i<=MAXR;i++){
  29.                 if(!fg->regv[i]) continue;
  30.                 if(p->code==ALLOCREG&&p->q1.reg==i) ierror(0);
  31.                 if((p->q1.flags&(VAR|DONTREGISTERIZE))==VAR&&p->q1.v==fg->regv[i]){
  32.                     p->q1.flags|=REG;
  33.                     p->q1.reg=i;
  34.                 }
  35.                 if((p->q2.flags&(VAR|DONTREGISTERIZE))==VAR&&p->q2.v==fg->regv[i]){
  36.                     p->q2.flags|=REG;
  37.                     p->q2.reg=i;
  38.                 }
  39.                 if((p->z.flags&(VAR|DONTREGISTERIZE))==VAR&&p->z.v==fg->regv[i]){
  40.                     p->z.flags|=REG;
  41.                     p->z.reg=i;
  42.                 }
  43.             }
  44.             if(p==fg->end) break;
  45.             p=p->next;
  46.         }
  47.         if(fg->start&&fg->start->code==LABEL) lic=fg->start;
  48.         for(i=1;i<=MAXR;i++){
  49.             if(fg->regv[i]){
  50.                 if(DEBUG&2048) printf("(%s),%d assigned to %s\n",fg->regv[i]->identifier,fg->regv[i]->offset,regnames[i]);
  51.                 if(BTST(fg->av_in,fg->regv[i]->index)){
  52.                 /*  Variable beim Eintritt aktiv?   */
  53.                     struct flowlist *lp;int flag;
  54.                     lp=fg->in;flag=0;
  55.                     /*  Parameter am Anfang laden?  */
  56.                     if(fg==fg1&&fg->regv[i]->offset<0) flag=1;
  57.                     while(lp){
  58.                         if(lp->graph&&lp->graph->regv[i]!=fg->regv[i]&&BTST(lp->graph->av_out,fg->regv[i]->index)){ flag=1;break; }
  59.                         lp=lp->next;
  60.                     }
  61.                     if(flag){
  62.                         if(DEBUG&2048) printf("\thave to load it at start of block\n");
  63.  
  64.                         new=mymalloc(ICS);
  65.                         new->code=ASSIGN;
  66.                         new->typf=fg->regv[i]->vtyp->flags;
  67.                         new->q1.flags=VAR|DONTREGISTERIZE;
  68.                         new->q1.val.vlong=l2zl(0L);
  69.                         new->q1.v=fg->regv[i];
  70.                         new->q2.flags=0;
  71.                         new->q2.reg=szof(fg->regv[i]->vtyp);
  72.                         new->z.flags=VAR|REG;
  73.                         new->z.val.vlong=l2zl(0L);
  74.                         new->z.v=fg->regv[i];
  75.                         new->z.reg=i;
  76.                         new->q1.am=new->q2.am=new->z.am=0;
  77.                         insert_IC_fg(fg,lic,new);
  78.                     }
  79.                 }
  80.                 if(BTST(fg->av_out,fg->regv[i]->index)){
  81.                 /*  Variable beim Austritt aktiv?   */
  82.                     struct flowlist *lp;int flag=0;
  83.                     /*  Wert muss gespeichert werden, falls ein Vorgaenger  */
  84.                     /*  eines Nachfolgers den Wert nicht im selben Register */
  85.                     if((fg->normalout&&(!fg->normalout->end||fg->normalout->end->code!=BRA))&&BTST(fg->normalout->av_in,fg->regv[i]->index)){
  86.                         if(fg->normalout->regv[i]!=fg->regv[i]) flag=1;
  87.                         lp=fg->normalout->in;
  88.                         while(!flag&&lp){
  89.                             if(lp->graph&&lp->graph->regv[i]!=fg->regv[i]){ flag=1; break; }
  90.                             lp=lp->next;
  91.                         }
  92.                     }
  93.                     if(!flag&&fg->branchout&&BTST(fg->branchout->av_in,fg->regv[i]->index)){
  94.                         if(fg->branchout->regv[i]!=fg->regv[i]) flag=1;
  95.                         lp=fg->branchout->in;
  96.                         while(!flag&&lp){
  97.                             if(lp->graph&&lp->graph->regv[i]!=fg->regv[i]){ flag=1; break; }
  98.                             lp=lp->next;
  99.                         }
  100.                     }
  101.                     if(flag){
  102.                         struct IC *tp;
  103.                         if(DEBUG&2048) printf("\thave to save it at end of block\n");
  104.                         new=mymalloc(ICS);
  105.                         new->code=ASSIGN;
  106.                         new->typf=fg->regv[i]->vtyp->flags;
  107.                         new->q1.flags=VAR|REG;
  108.                         new->q1.val.vlong=l2zl(0L);
  109.                         new->q1.v=fg->regv[i];
  110.                         new->q1.reg=i;
  111.                         new->q2.flags=0;
  112.                         new->q2.reg=szof(fg->regv[i]->vtyp);
  113.                         new->z.flags=VAR|DONTREGISTERIZE;
  114.                         new->z.val.vlong=l2zl(0L);
  115.                         new->z.v=fg->regv[i];
  116.                         new->q1.am=new->q2.am=new->z.am=0;
  117.                         /*  Vor FREEREGs und evtl. Branch+COMPARE/TEST setzen   */
  118.                         if(fg->end){
  119.                             tp=fg->end;
  120.                             while(tp!=fg->start&&tp->code==FREEREG)
  121.                                 tp=tp->prev;
  122.                             if(tp&&tp->code>=BEQ&&tp->code<=BRA){
  123.                                 if(tp->code<BRA){
  124.                                     int c;
  125.                                     do{
  126.                                         tp=tp->prev;
  127.                                         c=tp->code;
  128.                                         if(c!=FREEREG&&c!=COMPARE&&c!=TEST) ierror(0);
  129.                                     }while(c!=COMPARE&&c!=TEST);
  130.                                 }
  131.                                 tp=tp->prev;
  132.                             }
  133.                         }else tp=lic;
  134.                         insert_IC_fg(fg,tp,new);
  135.                     }
  136.                 }
  137.                 if(!lfg||!lfg->regv[i]) insert_allocreg(fg,lic,ALLOCREG,i);
  138.                 if(!fg->normalout||!fg->normalout->regv[i])
  139.                     insert_allocreg(fg,fg->end?fg->end:lic,FREEREG,i);
  140.             }
  141.         }
  142.         if(fg->end) lic=fg->end;
  143.         lfg=fg;
  144.         fg=fg->normalout;
  145.     }
  146. }
  147.  
  148. void do_loop_regs(struct flowgraph *start,struct flowgraph *end)
  149. /*  macht die Variablenzuweisung in Schleife start-end  */
  150. {
  151.     struct flowgraph *g,*e;
  152.     int i,r,is_loop,flag;
  153.     struct Var *lregs[MAXR+1]={0};
  154.     unsigned char rused[(MAXR+CHAR_BIT)/CHAR_BIT];
  155.     if(start->loopend){
  156.         is_loop=1;
  157.         if(start!=end){
  158.             g=start->normalout;
  159.             while(g&&g!=end){
  160.                 e=g->loopend;
  161.                 if(e){
  162.                     do_loop_regs(g,e);
  163.                     g=e;
  164.                 }
  165.                 g=g->normalout;
  166.             }
  167.         }
  168.     }else{
  169.         is_loop=0;
  170.         if(DEBUG&1024) printf("global register allocation\n");
  171.     }
  172.     if(DEBUG&1024) printf("assigning regs to blocks %d to %d\n",start->index,end->index);
  173.     /*  berechnen, wieviel ungefaehr eingespart wird, wenn eine Variable    */
  174.     /*  fuer diese Schleife in einem best. Register gehalten wird           */
  175.     if(DEBUG&1024) printf("calculating approximate savings\n");
  176.     /*  alle auf 0  */
  177.     for(i=0;i<vcount-rcount;i++){
  178.         for(r=1;r<=MAXR;r++){
  179.             savings[i][r]=0;
  180.             if(!is_loop){
  181.                 if(vilist[i]->offset<0&&(vilist[i]->storage_class==REGISTER||vilist[i]->storage_class==AUTO))
  182.                     savings[i][r]=-1;
  183.             }
  184.         }
  185.     }
  186.     g=start;
  187.     while(g){
  188.         struct IC *p;struct Var *v;
  189.         int t,vt;
  190.         e=g->loopend;
  191.         if(e&&g!=start){
  192.             /*  innere Schleifen schon erledigt; nur noch schauen, ob Variablen */
  193.             /*  in denselben Registern verbleiben                               */
  194.             /*  innere Schleife ueberspringen - nur noch zaehlen, wie oft   */
  195.             /*  jedes Register von temporaeren Variablen belegt ist; wie    */
  196.             /*  viel das ausmacht, kann aber nur geschaetzt werden          */
  197.             while(g&&g!=e->normalout){
  198.                 for(r=1;r<=MAXR;r++){
  199.                     if(g->regv[r]){
  200.                         if(DEBUG&2048) printf("inner loop has (%s),%d assigned to %s\n",g->regv[r]->identifier,g->regv[r]->offset,regnames[r]);
  201.                         if(BTST(g->av_in,g->regv[r]->index)) savings[g->regv[r]->index][r]++;
  202.                         if(BTST(g->av_out,g->regv[r]->index)) savings[g->regv[r]->index][r]++;
  203.                         /*  falls Variable schon in anderem Register    */
  204.                         for(i=1;i<=MAXR;i++)
  205.                             if(i!=r) savings[g->regv[r]->index][i]-=2;
  206.                     }
  207.                     if(BTST(g->regused,r)){
  208.                         int v;
  209.                         if(g->regv[r]) v=g->regv[r]->index; else v=-1;
  210.                         for(i=0;i<vcount-rcount;i++){
  211.                             if(BTST(g->av_in,i)&&i!=v) savings[i][r]-=2;
  212.                             if(BTST(g->av_out,i)&&i!=v) savings[i][r]-=2;
  213.                         }
  214.                     }else if(regscratch[r]&&g->calls>0){
  215.                         for(i=0;i<vcount-rcount;i++) savings[i][r]-=g->calls*2;
  216.                     }
  217.                 }
  218.                 g=g->normalout;
  219.             }
  220.             continue;
  221.         }
  222.         if(g->calls>0){
  223.         /*  bei Funktionsaufrufen muessen Scratchregister gespeichert werden */
  224.             for(r=1;r<=MAXR;r++)
  225.                 if(regscratch[r])
  226.                     for(i=0;i<vcount-rcount;i++) savings[i][r]-=g->calls*2;
  227.         }
  228.         /*  Wenn das Register in dem Block benutzt wird, muss man es retten */
  229.         for(r=1;r<=MAXR;r++){
  230.             if(BTST(g->regused,r)){
  231.                 int vi;
  232.                 if(g->regv[r]) vi=g->regv[r]->index; else vi=-1;
  233.                 for(i=0;i<vcount-rcount;i++)
  234.                     if(vi!=i) savings[i][r]-=2;
  235.             }
  236.         }
  237.         p=g->start;
  238.         while(p){
  239.             if((p->q1.flags&(VAR|VARADR|REG))==VAR){
  240.                 v=p->q1.v;
  241.                 if((v->storage_class==AUTO||v->storage_class==REGISTER)&&!(v->flags&USEDASADR)){
  242.                     vt=v->vtyp->flags&31;
  243.                     i=v->index;
  244.                     if(p->q1.flags&DREFOBJ) t=p->typf&31; else t=0;
  245.                     flag=0;
  246.                     if(!is_loop){
  247.                     /*  schauen, ob Variable schon in einem Register    */
  248.                         for(r=1;r<=MAXR;r++) if(g->regv[r]==v) {flag=1;break;}
  249.                     }
  250.                     if(!flag){
  251.                         for(r=1;r<=MAXR;r++){
  252.                             if(!regsa[r]&&!BTST(g->regused,r)){
  253.                                 /*  extra saving, falls passendes Reg fuer DREF */
  254.                                 if(t&®ok(r,vt,t)) savings[i][r]++;
  255.                                 if(regok(r,vt,0)) savings[i][r]++;
  256.                             }
  257.                         }
  258.                     }
  259.                 }
  260.             }
  261.             if((p->q2.flags&(VAR|VARADR|REG))==VAR){
  262.                 v=p->q2.v;
  263.                 if((v->storage_class==AUTO||v->storage_class==REGISTER)&&!(v->flags&USEDASADR)){
  264.                     vt=v->vtyp->flags&31;
  265.                     i=v->index;
  266.                     if(p->q2.flags&DREFOBJ) t=p->typf&31; else t=0;
  267.                     flag=0;
  268.                     if(!is_loop){
  269.                     /*  schauen, ob Variable schon in einem Register    */
  270.                         for(r=1;r<=MAXR;r++) if(g->regv[r]==v) {flag=1;break;}
  271.                     }
  272.                     if(!flag){
  273.                         for(r=1;r<=MAXR;r++){
  274.                             if(!regsa[r]&&!BTST(g->regused,r)){
  275.                                 /*  extra saving, falls passendes Reg fuer DREF */
  276.                                 if(t&®ok(r,vt,t)) savings[i][r]++;
  277.                                 if(regok(r,vt,0)) savings[i][r]++;
  278.                             }
  279.                         }
  280.                     }
  281.                 }
  282.             }
  283.             if((p->z.flags&(VAR|VARADR|REG))==VAR){
  284.                 v=p->z.v;
  285.                 if((v->storage_class==AUTO||v->storage_class==REGISTER)&&!(v->flags&USEDASADR)){
  286.                     vt=v->vtyp->flags&31;
  287.                     i=v->index;
  288.                     if(p->z.flags&DREFOBJ) t=p->typf&31; else t=0;
  289.                     flag=0;
  290.                     if(!is_loop){
  291.                     /*  schauen, ob Variable schon in einem Register    */
  292.                         for(r=1;r<=MAXR;r++) if(g->regv[r]==v) {flag=1;break;}
  293.                     }
  294.                     if(!flag){
  295.                         for(r=1;r<=MAXR;r++){
  296.                             if(!regsa[r]&&!BTST(g->regused,r)){
  297.                                 /*  extra saving, falls passendes Reg fuer DREF */
  298.                                 if(t&®ok(r,vt,t)) savings[i][r]++;
  299.                                 if(regok(r,vt,0)) savings[i][r]++;
  300.                             }
  301.                         }
  302.                     }
  303.                 }
  304.             }
  305.             if(p==g->end) break;
  306.             p=p->next;
  307.         }
  308.         if(g==end) break;
  309.         g=g->normalout;
  310.     }
  311.     /*  Maximum ermitteln   */
  312.     for(i=0;i<vcount-rcount;i++){
  313.         int m=0;
  314.         for(r=1;r<=MAXR;r++){
  315.             if(savings[i][r]>m) m=savings[i][r];
  316.         }
  317.         savings[i][0]=m;
  318.     }
  319.  
  320.     if(DEBUG&2048){
  321.         for(i=0;i<vcount-rcount;i++){
  322.             printf("(%s),%d(best=%d):\n",vilist[i]->identifier,vilist[i]->offset,savings[i][0]);
  323.             for(r=1;r<=MAXR;r++)
  324.                 printf("%s=%d ",regnames[r],savings[i][r]);
  325.             printf("\n");
  326.         }
  327.     }
  328.     /*  Suchen, welche Variablen/Registerkombination das beste Ergebnis */
  329.     /*  liefert. Nur angenaehert, da sonst wohl zu aufwendig. Simplex?  */
  330.     memset(rused,0,(MAXR+CHAR_BIT)/CHAR_BIT);
  331.     for(i=0;i<vcount-rcount;i++) rvlist[i]=i;
  332.     qsort(rvlist,vcount-rcount,sizeof(*rvlist),cmp_savings);
  333.     for(i=0;i<vcount-rcount;i++){
  334.         int use,m=0,vi;
  335.         vi=rvlist[i];
  336.         if(DEBUG&2048) printf("%d: (%s),%d(best=%d)\n",i,vilist[vi]->identifier,vilist[vi]->offset,savings[vi][0]);
  337.         for(r=1;r<=MAXR;r++){
  338.             if(!lregs[r]&&savings[vi][r]>m){
  339.                 m=savings[vi][r];
  340.                 use=r;
  341.                 if(m==savings[vi][0]) break;
  342.             }
  343.         }
  344.         if(m>0){
  345.             if(DEBUG&1024) printf("assigned (%s),%d to %s, saving=%d\n",vilist[vi]->identifier,vilist[vi]->offset,regnames[use],m);
  346.             lregs[use]=vilist[vi];
  347.             BSET(rused,use);
  348.         }
  349.     }
  350.     /*  Registervariablen in alle Bloecke der Schleife eintragen    */
  351.     /*  dabei beruecksichtigen, dass sie in manchen Bloecken nicht  */
  352.     /*  in Register kommen koennen, wenn das Register da schon von  */
  353.     /*  local_regs benutzt wird                                     */
  354.     if(DEBUG&1024) printf("propagate register vars\n");
  355.     g=start;
  356.     while(g){
  357.         for(r=1;r<=MAXR;r++){
  358.             if(lregs[r]&&!BTST(g->regused,r)){
  359.                 int flag=0;
  360.                 if(g->regv[r]) ierror(0);
  361.                 /*  Variable schon in anderem Register? */
  362.                 for(i=1;i<=MAXR;i++){
  363.                     if(i!=r&&g->regv[i]==lregs[r]){flag=1;break;}
  364.                 }
  365.                 if(!flag){
  366.                     g->regv[r]=lregs[r];
  367.                     BSET(g->regused,r);
  368.                 }
  369.             }
  370.         }
  371.         if(g==end) break;
  372.         g=g->normalout;
  373.     }
  374.     if(is_loop){
  375.         /*  in Schleifenvorkopf eintragen   */
  376.         if(start->in->graph->index>=0) ierror(0);
  377.         memcpy(&start->in->graph->regv,&start->regv,sizeof(start->regv));
  378.         memcpy(&start->in->graph->regused,rused,sizeof(rused));
  379.         /*  in Schleifenfuss eintragen   */
  380.         if(end->normalout->index>=0) ierror(0);
  381.         memcpy(&end->normalout->regv,&start->regv,sizeof(start->regv));
  382.         memcpy(&end->normalout->regused,rused,sizeof(rused));
  383.     }
  384. #if 0
  385.     /*  in start ausbessern, wenn einige Register belegt sind   */
  386.     for(r=1;r<=MAXR;r++)
  387.         if(BTST(start->regused,r)) start->regv[r]=0;
  388.     bvunite(start->regused,rused,(MAXR+CHAR_BIT)/CHAR_BIT);
  389. #endif
  390. }
  391. void block_regs(struct flowgraph *fg)
  392. /*  macht die Variablenzuweisung fuer einzelne Bloecke  */
  393. {
  394.     struct flowgraph *g,**fgp;
  395.     int i,r,changed,fgz;
  396.     if(DEBUG&1024) printf("block_regs\n");
  397.  
  398.     savings=mymalloc((vcount-rcount)*sizeof(*savings));
  399.     rvlist=mymalloc((vcount-rcount)*sizeof(*rvlist));
  400.  
  401.     /*  Array auf Bloecke im Flussgraphen mangels doppelter Verkettung  */
  402.     fgp=mymalloc(basic_blocks*sizeof(*fgp));
  403.     g=fg;fgz=0;
  404.     while(g){
  405.         fgp[fgz]=g;fgz++;
  406.         g=g->normalout;
  407.     }
  408.     if(fgz>basic_blocks) ierror(0); else basic_blocks=fgz;
  409.     /*  alle auf 0  */
  410.     do{
  411.         changed=0;
  412.         if(DEBUG&1024) printf("block_regs pass\n");
  413.         for(fgz=basic_blocks-1;fgz>=0;fgz--){
  414.             struct IC *p;struct Var *v;struct flowlist *lp;
  415.             int t,vt;
  416.             g=fgp[fgz];
  417.             if(DEBUG&2048) printf("assigning regs to block %d\n",g->index);
  418.             /*  berechnen, wieviel ungefaehr eingespart wird, wenn eine Variable    */
  419.             /*  fuer diesen Block in einem best. Register gehalten wird             */
  420.             if(DEBUG&2048) printf("calculating approximate savings\n");
  421.  
  422.             for(i=0;i<vcount-rcount;i++){
  423.                 for(r=1;r<=MAXR;r++){
  424.                     if(!g->regv[r]||g->regv[r]->index!=i){
  425.                         int w=0;
  426.                         /*  Variable muss evtl. geladen/gespeichert werden  */
  427.                         if(BTST(g->av_in,i)) w--;
  428.                         if(BTST(g->av_out,i)) w--;
  429.                         savings[i][r]=w;
  430.                     }
  431.                 }
  432.             }
  433.             if(g->calls>0){
  434.             /*  bei Funktionsaufrufen muessen Scratchregister gespeichert werden */
  435.                 for(r=1;r<=MAXR;r++)
  436.                     if(regscratch[r])
  437.                         for(i=0;i<vcount-rcount;i++) savings[i][r]-=g->calls*2;
  438.             }
  439.             /*  Wenn Vorgaenger/Nachfolger selbe Variable im selben */
  440.             /*  Register hat, entfaellt Laden/Speichern in diesem   */
  441.             /*  Block und vermutlich auch im Vorgaenger/Nachfolger  */
  442.             /*  nicht immer, aber naeherungsweise...                */
  443.             lp=g->in;
  444.             while(lp){
  445.                 if(lp->graph){
  446.                     for(r=1;r<=MAXR;r++){
  447.                         if(lp->graph->regv[r]&&BTST(g->av_in,lp->graph->regv[r]->index)) savings[lp->graph->regv[r]->index][r]+=2;
  448.                     }
  449.                 }
  450.                 lp=lp->next;
  451.             }
  452.             if(g->branchout){
  453.                 for(r=1;r<=MAXR;r++){
  454.                     if(g->branchout->regv[r]&&BTST(g->av_out,g->branchout->regv[r]->index)) savings[g->branchout->regv[r]->index][r]+=2;
  455.                 }
  456.             }
  457.             if(g->normalout&&(!g->normalout->end||g->normalout->end->code!=BRA)){
  458.                 for(r=1;r<=MAXR;r++){
  459.                     if(g->normalout->regv[r]&&BTST(g->av_out,g->normalout->regv[r]->index)) savings[g->normalout->regv[r]->index][r]+=2;
  460.                 }
  461.             }
  462.  
  463.             p=g->start;
  464.             while(p){
  465.                 if((p->q1.flags&(VAR|VARADR|REG))==VAR){
  466.                     v=p->q1.v;
  467.                     if((v->storage_class==AUTO||v->storage_class==REGISTER)&&!(v->flags&USEDASADR)){
  468.                         vt=v->vtyp->flags&31;
  469.                         i=v->index;
  470.                         if(p->q1.flags&DREFOBJ) t=p->typf&31; else t=0;
  471.                         for(r=1;r<=MAXR;r++){
  472.                             if(!regsa[r]&&!BTST(g->regused,r)){
  473.                                 /*  extra saving, falls passendes Reg fuer DREF */
  474.                                 if(t&®ok(r,vt,t)) savings[i][r]++;
  475.                                 if(regok(r,vt,0)) savings[i][r]++;
  476.                             }
  477.                         }
  478.                     }
  479.                 }
  480.                 if((p->q2.flags&(VAR|VARADR|REG))==VAR){
  481.                     v=p->q2.v;
  482.                     if((v->storage_class==AUTO||v->storage_class==REGISTER)&&!(v->flags&USEDASADR)){
  483.                         vt=v->vtyp->flags&31;
  484.                         i=v->index;
  485.                         if(p->q2.flags&DREFOBJ) t=p->typf&31; else t=0;
  486.                         for(r=1;r<=MAXR;r++){
  487.                             if(!regsa[r]&&!BTST(g->regused,r)){
  488.                                 /*  extra saving, falls passendes Reg fuer DREF */
  489.                                 if(t&®ok(r,vt,t)) savings[i][r]++;
  490.                                 if(regok(r,vt,0)) savings[i][r]++;
  491.                             }
  492.                         }
  493.                     }
  494.                 }
  495.                 if((p->z.flags&(VAR|VARADR|REG))==VAR){
  496.                     v=p->z.v;
  497.                     if((v->storage_class==AUTO||v->storage_class==REGISTER)&&!(v->flags&USEDASADR)){
  498.                         vt=v->vtyp->flags&31;
  499.                         i=v->index;
  500.                         if(p->z.flags&DREFOBJ) t=p->typf&31; else t=0;
  501.                         for(r=1;r<=MAXR;r++){
  502.                             if(!regsa[r]&&!BTST(g->regused,r)){
  503.                                 /*  extra saving, falls passendes Reg fuer DREF */
  504.                                 if(t&®ok(r,vt,t)) savings[i][r]++;
  505.                                 if(regok(r,vt,0)) savings[i][r]++;
  506.                             }
  507.                         }
  508.                     }
  509.                 }
  510.                 if(p==g->end) break;
  511.                 p=p->next;
  512.             }
  513.             /*  moegliche Kandidaten suchen; muss nicht immer die beste */
  514.             /*  Kombination finden, sollte aber bei lokaler Vergabe     */
  515.             /*  selten einen Unterschied machen                         */
  516.             for(r=1;r<=MAXR;r++){
  517.                 if(g->regv[r]||BTST(g->regused,r)) continue;
  518.                 for(i=0;i<vcount-rcount;i++){
  519.                     if(savings[i][r]>0){
  520.                         int flag;struct Var *v=vilist[i];
  521.                         /*  Variable schon in anderem Register? */
  522.                         for(flag=1;flag<=MAXR;flag++)
  523.                             if(g->regv[flag]==v){flag=-1;break;}
  524.                         if(flag>0){
  525.                             if(DEBUG&1024) printf("assigned (%s),%d to %s; saving=%d\n",vilist[i]->identifier,vilist[i]->offset,regnames[r],savings[i][r]);
  526.                             g->regv[r]=vilist[i];
  527.                             BSET(g->regused,r);
  528.                             changed=1;
  529.                             break;
  530.                         }
  531.                     }
  532.                 }
  533.             }
  534.         }
  535.     }while(changed);
  536.     /*  jetzt nochmal globale Register vergeben */
  537. /*    do_loop_regs(fgp[0],fgp[basic_blocks-1]);*/
  538.  
  539.     free(fgp);
  540.     free(rvlist);
  541.     free(savings);
  542. }
  543.  
  544. void loop_regs(struct flowgraph *fg)
  545. /*  weist Variablen in Schleifen Register zu    */
  546. {
  547.     struct flowgraph *g,*first=fg;
  548.     if(DEBUG&1024) printf("assigning regs in loops\n");
  549.     savings=mymalloc((vcount-rcount)*sizeof(*savings));
  550.     rvlist=mymalloc((vcount-rcount)*sizeof(*rvlist));
  551.     while(fg){
  552.         g=fg->loopend;
  553.         if(g){
  554.             do_loop_regs(fg,g);
  555.             fg=g;
  556.         }
  557.         if(!fg->normalout){
  558.         /*  jetzt nochmal global Register vergeben  */
  559.             do_loop_regs(first,fg);
  560.         }
  561.         fg=fg->normalout;
  562.     }
  563.     free(rvlist);
  564.     free(savings);
  565. }
  566. void insert_allocreg(struct flowgraph *fg,struct IC *p,int code,int reg)
  567. /*  fuegt ein ALLOCREG/FREEREG (in code) hinter p ein - bei p==0 in */
  568. /*  first_ic                                                        */
  569. {
  570.     struct IC *new=mymalloc(ICS);
  571.     BSET(fg->regused,reg);
  572.     regused[reg]=1;
  573.     new->code=code;
  574.     new->typf=0;
  575.     new->q1.am=new->q2.am=new->z.am=0;
  576.     new->q1.flags=REG;
  577.     new->q1.reg=reg;
  578.     new->q2.flags=new->z.flags=0;
  579.     insert_IC_fg(fg,p,new);
  580. }
  581.  
  582. struct Var *lregv[MAXR+1];
  583. struct flowgraph *lfg;
  584.  
  585. int replace_local_reg(struct obj *o)
  586. /*  tested, ob o eine Scratch-Variable ist und ersetzt sie gegebenenfalls   */
  587. {
  588.     unsigned int i;struct Var *v;
  589.     if((o->flags&(VAR|REG|VARADR))==VAR){
  590.         v=o->v;i=v->index;
  591.         if(BTST(lfg->av_kill,i)&&!BTST(lfg->av_out,i)){
  592.             for(i=1;i<=MAXR;i++){
  593.                 if(lregv[i]==v){
  594.                     o->flags|=(REG|SCRATCH);
  595. /*                    o->flags&=~VAR;*/
  596.                     o->reg=i;
  597.                     return(i);
  598.                 }
  599.             }
  600.         }
  601.     }
  602.     return(0);
  603. }
  604. void local_regs(struct flowgraph *fg)
  605. /*  versucht Variablen, die nur innerhalb eines Basic Blocks benutzt    */
  606. /*  werden (kill==true und out==false), Register zuzuweisen.            */
  607. {
  608.     struct IC *p; struct Var *v;
  609.     int i,t,r,nr,mustalloc,regu[MAXR+1];
  610.     if(DEBUG&1024) printf("assigning temporary variables to registers\n");
  611.     lfg=fg;
  612.     while(lfg){
  613.         for(i=1;i<=MAXR;i++){ lregv[i]=0; regu[i]=regsa[i]; lfg->regv[i]=0;}
  614.         memset(&lfg->regused,0,(MAXR+CHAR_BIT)/CHAR_BIT);
  615.         lfg->calls=0;
  616.         p=lfg->end;
  617.         while(p){
  618.             i=replace_local_reg(&p->z);
  619.             if(i&&!(p->z.flags&DREFOBJ)){
  620.                 lregv[i]=0;regu[i]--;
  621.                 nr=i;mustalloc=1;
  622.                 if(DEBUG&2048) printf("regu[%s] decremented to %d\n",regnames[i],regu[i]);
  623.             }else nr=0;
  624.             if(p->code!=ADDRESS){
  625.                 if(replace_local_reg(&p->q1)==nr) mustalloc=0;
  626.                 if(replace_local_reg(&p->q2)==nr) mustalloc=0;
  627.             }
  628.             /*  hier wegen USEQ2ASZ aufpassen; kommutative ICs sollten so   */
  629.             /*  angeordnet werden, dass ein evtl. Register rechts steht     */
  630.             if((p->q2.flags&(VAR|REG|VARADR))==VAR&&!(p->q2.v->flags&USEDASADR)&&!(p->q2.v->vtyp->flags&VOLATILE)&&(p->q2.v->storage_class==AUTO||p->q2.v->storage_class==REGISTER)){
  631.                 i=p->q2.v->index;
  632.                 if(BTST(lfg->av_kill,i)&&!BTST(lfg->av_out,i)){
  633.                     t=p->q2.v->vtyp->flags;
  634.                     if(USEQ2ASZ&&nr&®ok(nr,t,0)&&(!(p->q2.flags&DREFOBJ)||regok(nr,t,p->typf))) r=nr; else r=0;
  635.                     for(i=0;r==0&&i<=MAXR;i++){
  636.                         if(!regu[i]&&!regsa[i]&®ok(i,t,0)&&(USEQ2ASZ||i!=nr)) {r=i;break;}
  637.                     }
  638.                     if(r){
  639.                         if(r!=nr) insert_allocreg(lfg,p,FREEREG,r);
  640.                             else mustalloc=0;
  641.                         lregv[r]=p->q2.v;regused[r]=regu[r]=1;
  642.                         if(replace_local_reg(&p->q2)!=r) ierror(0);
  643.                         replace_local_reg(&p->q1);
  644.                         replace_local_reg(&p->z);
  645.                         if((DEBUG&1024)&&*p->q2.v->identifier) printf("temporary <%s> assigned to %s\n",p->q2.v->identifier,regnames[r]);
  646.                         if(DEBUG&2048) printf("temporary <%s> assigned to %s\n",p->q2.v->identifier,regnames[r]);
  647.                     }
  648.                 }
  649.             }
  650.             if((p->z.flags&(VAR|REG|DREFOBJ))==(VAR|DREFOBJ)&&!(p->z.v->flags&USEDASADR)&&!(p->z.v->vtyp->flags&VOLATILE)&&(p->z.v->storage_class==AUTO||p->z.v->storage_class==REGISTER)){
  651.                 i=p->z.v->index;
  652.                 if(BTST(lfg->av_kill,i)&&!BTST(lfg->av_out,i)){
  653.                     for(r=0,i=0,t=p->z.v->vtyp->flags;i<=MAXR;i++){
  654.                         if(!regu[i]&&!regsa[i]&®ok(i,t,0)) {r=i;break;}
  655.                     }
  656.                     if(r){
  657.                         insert_allocreg(lfg,p,FREEREG,r);
  658.                         lregv[r]=p->z.v;regused[r]=regu[r]=1;
  659.                         if(replace_local_reg(&p->z)!=r){
  660.                             for(i=1;i<=MAXR;i++) if(lregv[i]) printf("%d:%s=%s(%p)\n",i,regnames[i],lregv[i]->identifier,lregv[i]);
  661.                             ierror(r);}
  662.                         replace_local_reg(&p->q1);
  663.                         if((DEBUG&1024)&&*p->z.v->identifier) printf("temporary <%s> assigned to %s\n",p->z.v->identifier,regnames[r]);
  664.                         if(DEBUG&2048) printf("temporary <%s> assigned to %s\n",p->z.v->identifier,regnames[r]);
  665.                     }
  666.                 }
  667.             }
  668.             if((p->q1.flags&(VAR|REG|VARADR))==VAR&&!(p->q1.v->flags&USEDASADR)&&!(p->q1.v->vtyp->flags&VOLATILE)&&(p->q1.v->storage_class==AUTO||p->q1.v->storage_class==REGISTER)){
  669.                 i=p->q1.v->index;
  670.                 if(BTST(lfg->av_kill,i)&&!BTST(lfg->av_out,i)){
  671.                     t=p->q1.v->vtyp->flags;
  672.                     if(nr&®ok(nr,t,0)&&(!(p->q1.flags&DREFOBJ)||regok(nr,t,p->typf))) r=nr; else r=0;
  673.                     for(i=0;r==0&&i<=MAXR;i++){
  674.                         if(!regu[i]&&!regsa[i]&®ok(i,t,0)) {r=i;break;}
  675.                     }
  676.                     if(r){
  677.                         if(r!=nr) insert_allocreg(lfg,p,FREEREG,r);
  678.                             else mustalloc=0;
  679.                         lregv[r]=p->q1.v;regused[r]=regu[r]=1;
  680.                         if(replace_local_reg(&p->q1)!=r) ierror(0);
  681.                         if((DEBUG&1024)&&*p->q1.v->identifier) printf("temporary <%s> assigned to %s\n",p->q1.v->identifier,regnames[r]);
  682.                         if(DEBUG&2048) printf("temporary <%s> assigned to %s\n",p->q1.v->identifier,regnames[r]);
  683.                     }
  684.                 }
  685.             }
  686.             if(p->code==CALL){
  687.                 lfg->calls++;
  688.                 /*  falls Scratchregister bei Funktionsaufruf benutzt   */
  689.                 /*  wird, moeglichst auf ein anderes ausweichen         */
  690.                 for(i=1;i<=MAXR;i++){
  691.                     if(lregv[i]&®scratch[i]){
  692.                         int r;
  693.                         for(r=1;r<=MAXR;r++){
  694.                             if(!lregv[r]&&!regscratch[r]&®ok(r,lregv[i]->vtyp->flags,0)){
  695.                             /*  noch schauen, ob es benutzt wurde   */
  696.                                 struct IC *ip=p;int flag=0;
  697.                                 while(!(ip->code==FREEREG&&ip->q1.reg==i)){
  698.                                     if(ip->code==ALLOCREG&&ip->q1.reg==r){flag=1;break;}
  699.                                     ip=ip->next;
  700.                                 }
  701.                                 if(flag) continue;
  702.                                 do{
  703.                                     if((ip->q1.flags®)&&ip->q1.reg==i) ip->q1.reg=r;
  704.                                     if((ip->q2.flags®)&&ip->q2.reg==i) ip->q2.reg=r;
  705.                                     if((ip->z.flags®)&&ip->z.reg==i) ip->z.reg=r;
  706.                                     ip=ip->prev;
  707.                                 }while(ip!=p->prev);
  708.                                 lregv[r]=lregv[i];
  709.                                 BSET(lfg->regused,r);
  710.                                 regused[r]=regu[r]=1;
  711.                                 lregv[i]=0;regu[i]=0;
  712.                                 break;
  713.                             }
  714.                         }
  715.                     }
  716.                 }
  717.             }
  718.             /*  die Faelle beachten, wenn schon im IC ein Register          */
  719.             /*  angesprochen wird (sollte nur bei CALL und return auftreten */
  720.             if(p->code==FREEREG){
  721.                 ierror(0);
  722.                 if(regu[p->q1.reg]) remove_IC_fg(lfg,p);
  723.                 regu[p->q1.reg]++;
  724.             }
  725.             if(p->code==ALLOCREG){
  726.                 ierror(0);
  727.                 if(regu[p->q1.reg]==2) remove_IC_fg(lfg,p);
  728.                 regu[p->q1.reg]--;
  729.             }
  730.             if(p==lfg->start) i=1; else i=0;;
  731.             p=p->prev;
  732.             if(nr&&mustalloc) insert_allocreg(lfg,p,ALLOCREG,nr);
  733.             if(i) break;
  734.         }
  735.         lfg=lfg->normalout;
  736.     }
  737. }
  738. void insert_saves(void)
  739. /*  fuegt speichern von Registern bei Funktionsaufrufen ein */
  740. {
  741.     int i,c;struct IC *p;
  742.     if(DEBUG&1024) printf("insert_saves\n");
  743.     for(i=1;i<=MAXR;i++) regs[i]=regsa[i];
  744.     for(p=first_ic;p;p=p->next){
  745.         c=p->code;
  746.         if(c==ALLOCREG) regs[p->q1.reg]=1;
  747.         if(c==FREEREG)  regs[p->q1.reg]=0;
  748.         if(c==CALL){
  749.             struct IC *s;
  750.             /*  das Wiederherstellen nach dem GETRETURN     */
  751.             s=p;
  752.             if(s->next&&s->next->code==FREEREG) {s=s->next;regs[s->q1.reg]=0;}
  753.             if(s->next&&s->next->code==GETRETURN) s=s->next;
  754.             if(s->next&&s->next->code==ALLOCREG&&s->next->next&&s->next->next->code==GETRETURN) s=s->next->next;
  755.             savescratch(MOVEFROMREG,p->prev,0);
  756.             savescratch(MOVETOREG,s,0);
  757.         }
  758.     }
  759. }
  760.  
  761. #endif
  762.  
  763. void simple_regs(void)
  764. /*  haelt Variablen in Registern, simple Version            */
  765. {
  766.     int i2,i,j;int pri;struct Var *v;
  767.     struct IC *icp,*start=first_ic;
  768.     if(!first_ic) return;
  769.     for(i2=0;i2<=MAXR*4;i2++){
  770.         int only_best,pointertype;
  771.         if(i2<=MAXR*2){i=i2;only_best=1;} else {i=i2/2;pointertype=only_best=0;}
  772.         if(i>MAXR){
  773.             i-=MAXR;
  774.             if(regsv[i]) continue;
  775.         }else{
  776.             regsv[i]=0;
  777.             /*  Ziehe Scratchregister vor, wenn kein Funktionsaufruf */
  778.             /*  erfolgt, sonst erst andere                           */
  779.             if(!function_calls&&!regscratch[i]) continue;
  780.             if(function_calls&®scratch[i]) continue;
  781.         }
  782.         if(regused[i]) continue;
  783.         /* Nicht-Scratchregister muessen einmal gesichert und wieder    */
  784.         /* hergestellt werden, Scratchregister bei jedem Call           */
  785.         if(regscratch[i]) pri=function_calls*2; else /*pri=2;*/ pri=0;
  786.         for(j=0;j<=1;j++){
  787.             if(j==0) v=merk_varf; else v=first_var[1];
  788.             while(v){
  789.                 if(v->storage_class==AUTO||v->storage_class==REGISTER){
  790.                     if(!(v->flags&USEDASADR)&&!(v->vtyp->flags&VOLATILE)){
  791.                         if(only_best&&v->vtyp->next) pointertype=v->vtyp->next->flags;
  792.                         if(v->priority>pri&®ok(i,v->vtyp->flags&31,pointertype)){
  793.                             regsv[i]=v;pri=v->priority;
  794.                         }
  795.                     }
  796.                 }
  797.                 v=v->next;
  798.             }
  799.         }
  800.         if(regsv[i]){
  801.             if(DEBUG&1) printf("Assigned <%s> to %s\n",regsv[i]->identifier,regnames[i]);
  802.             regsv[i]->priority=0;regused[i]=1;
  803.             if(regsv[i]->offset<0&&!(regsv[i]->flags&CONVPARAMETER)){
  804.                 icp=(struct IC *)mymalloc(ICS);
  805.                 icp->q1.am=icp->q2.am=icp->z.am=0;
  806.                 icp->code=ASSIGN;
  807.                 icp->typf=regsv[i]->vtyp->flags&31;
  808.                 icp->q1.flags=VAR;
  809.                 icp->q1.v=regsv[i];
  810.                 icp->q1.val.vlong=l2zl(0L);
  811.                 icp->q2.flags=0;
  812.                 icp->q2.reg=szof(regsv[i]->vtyp);
  813.                 icp->z.flags=REG;
  814.                 icp->z.reg=i;
  815.                 icp->next=first_ic;
  816.                 icp->prev=0;
  817.                 first_ic->prev=icp;
  818.                 first_ic=icp;
  819.             }
  820.             icp=(struct IC *)mymalloc(ICS);
  821.             icp->q1.am=icp->q2.am=icp->z.am=0;
  822.             icp->code=ALLOCREG;
  823.             icp->q1.flags=REG;
  824.             icp->q1.reg=i;
  825.             icp->q2.flags=icp->z.flags=icp->typf=0;
  826.             icp->next=first_ic;
  827.             icp->prev=0;
  828.             first_ic->prev=icp;
  829.             first_ic=icp;
  830.             icp=(struct IC *)mymalloc(ICS);
  831.             icp->q1.am=icp->q2.am=icp->z.am=0;
  832.             icp->code=FREEREG;
  833.             icp->q1.flags=REG;
  834.             icp->q1.reg=i;
  835.             icp->q2.flags=icp->z.flags=icp->typf=0;
  836.             icp->next=0;
  837.             add_IC(icp);
  838.         }
  839.     }
  840.     icp=start;
  841.     while(icp){
  842.         if((icp->code==ALLOCREG||icp->code==FREEREG)&®sv[icp->q1.reg]){
  843.         /*  irgendwelche allocreg/freereg im Code entfernen     */
  844.         /*  sollte nur beim Returnregister vorkommen            */
  845.             struct IC *m=icp->next;
  846.             remove_IC(icp);
  847.             icp=m;continue;
  848.         }
  849.         for(i=1;i<=MAXR;i++){
  850.             if(!regsv[i]) continue;
  851.             if((icp->q1.flags&(VAR|DONTREGISTERIZE))==VAR&&icp->q1.v==regsv[i]){
  852.                 icp->q1.flags|=REG;
  853.                 icp->q1.reg=i;
  854.             }
  855.             if((icp->q2.flags&(VAR|DONTREGISTERIZE))==VAR&&icp->q2.v==regsv[i]){
  856.                 icp->q2.flags|=REG;
  857.                 icp->q2.reg=i;
  858.             }
  859.             if((icp->z.flags&(VAR|DONTREGISTERIZE))==VAR&&icp->z.v==regsv[i]){
  860.                 icp->z.flags|=REG;
  861.                 icp->z.reg=i;
  862.             }
  863.         }
  864.         icp=icp->next;
  865.     }
  866. }
  867.  
  868.  
  869.